package com.ctshk.rpc.order.custom.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.common.vo.OrderRefundDTO;
import com.ctshk.rpc.custom.req.trip.CustomizedTripScheduleDTO;
import com.ctshk.rpc.custom.service.ICustomizedTripScheduleService;
import com.ctshk.rpc.finance.json.AccountJson;
import com.ctshk.rpc.finance.req.bill.BillAddRefundReq;
import com.ctshk.rpc.finance.req.bill.BillOperateRefundReq;
import com.ctshk.rpc.finance.service.IFinanceBillService;
import com.ctshk.rpc.insurance.dto.CancelDTO;
import com.ctshk.rpc.insurance.req.tp.CancelReq;
import com.ctshk.rpc.insurance.service.IInsuranceService;
import com.ctshk.rpc.order.custom.code.CollectionRefundWayIdCode;
import com.ctshk.rpc.order.custom.code.CurrencyIdCode;
import com.ctshk.rpc.order.custom.code.RefundDetailTypeCode;
import com.ctshk.rpc.order.custom.dto.order.*;
import com.ctshk.rpc.order.custom.entity.*;
import com.ctshk.rpc.order.custom.mapper.*;
import com.ctshk.rpc.order.custom.req.order.*;
import com.ctshk.rpc.order.custom.req.schedule.TripScheduleInfoReq;
import com.ctshk.rpc.order.custom.req.tourist.CustomOrderTouristIdReq;
import com.ctshk.rpc.order.custom.service.ICustomizedOrderTouristRefundService;
import com.ctshk.rpc.order.custom.util.OrderUtil;
import com.ctshk.rpc.order.custom.util.PacificUtil;
import com.ctshk.rpc.system.dto.MainDataCurrencyQueryDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.req.MainDataCurrencyUpdateStatusReq;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 游客退款记录 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-02-22
 */
@DubboService
public class CustomizedOrderTouristRefundServiceImpl extends ServiceImpl<CustomizedOrderTouristRefundMapper, CustomizedOrderTouristRefund> implements ICustomizedOrderTouristRefundService {

    @Autowired
    private CustomizedOrderTouristRefundMapper orderTouristRefundMapper;
    @Autowired
    private CustomizedOrderTouristInfoMapper orderTouristInfoMapper;
    @Autowired
    private CustomizedOrderAmountStatisticsMapper orderAmountStatisticsMapper;
    @Autowired
    private CustomizedOrderTouristVisaMapper orderTouristVisaMapper;
    @Autowired
    private CustomizedOrderTouristRefundDetailMapper orderTouristRefundDetailMapper;
    @Autowired
    private CustomizedOrderCollectionMapper orderCollectionMapper;
    @Autowired
    private CustomizedOrderMapper orderMapper;
    @Autowired
    private CustomizedOrderInsuranceMapper orderInsuranceMapper;
    @Autowired
    private CustomizedOrderInsuranceJoinMapper orderInsuranceJoinMapper;
    @Autowired
    private CustomizedOrderInsurancePriceTouristMapper orderInsurancePriceTouristMapper;
    @Autowired
    private CustomizedOrderReceiptInsuranceMapper orderReceiptInsuranceMapper;
    @Autowired
    private CustomizedOrderTouristOtherFeeMapper orderTouristOtherFeeMapper;

    @DubboReference
    private ICustomizedTripScheduleService tripScheduleService;
    //审批服务
    @DubboReference
    private ISysApprovalService sysApprovalService;
    @DubboReference
    private IMainDataCurrencyService mainDataCurrencyService;
    @DubboReference
    private IFinanceBillService financeBillService;
    @DubboReference
    private ISysUserService sysUserService;
    @DubboReference
    private IMainDataCurrencyService iMainDataCurrencyService;
    @DubboReference
    private IInsuranceService insuranceService;



    /**
     * 退款记录列表
     *
     * @param req
     * @return
     */
    @Override
    public PageResponse<CustomOrderTouristRefundListDTO> list(CustomOrderTouristRefundListReq req) {
        IPage<CustomOrderTouristRefundListReq> pageParam = new Page<>(req.getPageNo(), req.getPageSize());
        IPage<CustomOrderTouristRefundListDTO> pageResult = orderTouristRefundMapper.selectListBySelective(pageParam, req);
        PageResponse<CustomOrderTouristRefundListDTO> pageResponse = new PageResponse<>(pageResult.getRecords(),
                pageResult.getCurrent() == 1,
                pageResult.getTotal() <= (pageResult.getCurrent() * pageResult.getSize()),
                pageResult.getTotal(), pageResult.getCurrent(),
                pageResult.getSize());
        return pageResponse;
    }

    /**
     * 团期详情-退款明细
     *
     * @param req
     * @return
     */
    @Override
    public List<CustomOrderTouristRefundListDTO> scheduleRefundList(TripScheduleInfoReq req) {
        List<CustomOrderTouristRefundListDTO> list = orderTouristRefundMapper.scheduleRefundList(req.getScheduleId());
        if (list != null){
            list.forEach(dto -> {
                if (dto.getCreateId() != null){
                    UserDTO userDTO = sysUserService.queryCacheUser(dto.getCreateId());
                    dto.setCreateUserName(userDTO.getFullName());
                    dto.setCreateUserDept(userDTO.getDept());
                }
            });
            return list;
        }
        return null;
    }

    /**
     * 退款
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(CustomOrderTouristRefundAddReq req) {
        //明细不能重复录入
        int insurance = 0;
        int visa = 0;
        //申请退款总金额
        BigDecimal totalRefundAmount = BigDecimal.ZERO;
        for (CustomOrderTouristRefundAddItemReq itemReq : req.getItemList()) {
            if (Objects.equals(RefundDetailTypeCode.INSURANCE.getCode(), itemReq.getRefundDetailTypeId())) {
                insurance++;
            }
            if (Objects.equals(RefundDetailTypeCode.VISA.getCode(), itemReq.getRefundDetailTypeId())) {
                visa++;
            }
            BigDecimal hkdAmount = iMainDataCurrencyService.getHkdAmount(itemReq.getCurrencyId(), itemReq.getRefundAmount());
            if (hkdAmount != null){
                totalRefundAmount = totalRefundAmount.add(hkdAmount);
            }
        }
        //保险/签证，只能退款一次
        if (insurance >= 2) {
            throw new BusinessException(SystemError.CUSTOM_ORDER_4014);
        }
        if (visa >= 2) {
            throw new BusinessException(SystemError.CUSTOM_ORDER_4015);
        }
        //TODO 总应收大于0

        Set<Long> refundDetailTypeIdSet = new HashSet<>();
        refundDetailTypeIdSet.add(RefundDetailTypeCode.INSURANCE.getCode());
        refundDetailTypeIdSet.add(RefundDetailTypeCode.VISA.getCode());
        List<CustomizedOrderTouristRefundDetail> dbDetailList = orderTouristRefundMapper.selectAddByRefundDetailTypeId(req, refundDetailTypeIdSet);
        for (CustomizedOrderTouristRefundDetail detail : dbDetailList) {
            if (Objects.equals(RefundDetailTypeCode.INSURANCE.getCode(), detail.getRefundDetailId())) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4014);
            }
            if (Objects.equals(RefundDetailTypeCode.VISA.getCode(), detail.getRefundDetailId())) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4015);
            }
        }
        LocalDateTime now = LocalDateTime.now();
        //游客统计
        QueryWrapper<CustomizedOrderTouristInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CustomizedOrderTouristInfo::getOrderId, req.getOrderId());
        queryWrapper.lambda().eq(CustomizedOrderTouristInfo::getId, req.getTouristId());
        queryWrapper.lambda().eq(CustomizedOrderTouristInfo::getIsDeleted, 0);
        CustomizedOrderTouristInfo touristInfo = orderTouristInfoMapper.selectOne(queryWrapper);
        if (touristInfo == null) {
            throw new BusinessException(SystemError.SYS_411);
        }
        if (touristInfo.getTotalPaidIn().compareTo(totalRefundAmount) < 0){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4052);
        }
        //订单统计
        QueryWrapper<CustomizedOrderAmountStatistics> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(CustomizedOrderAmountStatistics::getOrderId, req.getOrderId());
        CustomizedOrderAmountStatistics statistics = orderAmountStatisticsMapper.selectOne(queryWrapper2);
        if (statistics == null) {
            throw new BusinessException(SystemError.SYS_411);
        }
        //实收
        BigDecimal totalPaidIn = touristInfo.getTotalPaidIn();
        //调整费用
        BigDecimal adjustmentCost = touristInfo.getAdjustmentCost();
        Long refundId = IdWorker.getId();
        CustomizedOrderTouristRefund refund = EntityUtil.copy(req, CustomizedOrderTouristRefund.class);
//            refund.setRefundNumber(OrderUtil.getRefundNumber());
        refund.setId(refundId);
        refund.setRefundStatus(2);
        refund.setGmtCreate(now);
        refund.setGmtModified(now);
        refund.setCreateId(req.getUserId());
        refund.setModifiedId(req.getUserId());
        refund.setIsDeleted(0);
        refund.setRefundStatus(2);
        refund.setRefundAmount(totalRefundAmount);
        //发起审批
        Long approvalId = startApproval(refund.getId(),req.getOrderId(), req.getUserId(),totalRefundAmount);
        refund.setApprovalId(approvalId);
        int insert1 = orderTouristRefundMapper.insert(refund);
        if (insert1 <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        for (CustomOrderTouristRefundAddItemReq itemReq : req.getItemList()) {
            if (Objects.equals(RefundDetailTypeCode.GROUP_FEE.getCode(), itemReq.getRefundDetailTypeId())) {
                if (itemReq.getRefundAmount().compareTo(touristInfo.getGroupFee()) > 0 ||
                        itemReq.getRefundAmount().compareTo(totalPaidIn) > 0) {
                    throw new BusinessException(SystemError.CUSTOM_ORDER_4016);
                }
            } else if (Objects.equals(RefundDetailTypeCode.INSURANCE.getCode(), itemReq.getRefundDetailTypeId())) {
                //TODO 退款金额<=保险费，审核通过后，调用api退保，印花税
            } else if (Objects.equals(RefundDetailTypeCode.VISA.getCode(), itemReq.getRefundDetailTypeId())) {
                QueryWrapper<CustomizedOrderTouristVisa> queryWrapper3 = new QueryWrapper<>();
                queryWrapper3.lambda().eq(CustomizedOrderTouristVisa::getOrderId, req.getOrderId());
                queryWrapper3.lambda().eq(CustomizedOrderTouristVisa::getTouristId, req.getTouristId());
                CustomizedOrderTouristVisa dbVisa = orderTouristVisaMapper.selectOne(queryWrapper3);
                if(dbVisa != null) {
                    if (itemReq.getRefundAmount().compareTo(dbVisa.getVisaAmount()) > 0 ||
                            itemReq.getRefundAmount().compareTo(totalPaidIn) > 0) {
                        throw new BusinessException(SystemError.CUSTOM_ORDER_4016);
                    }
                }
            } else if (Objects.equals(RefundDetailTypeCode.ADJUST.getCode(), itemReq.getRefundDetailTypeId())) {
                if (itemReq.getRefundAmount().compareTo(touristInfo.getAdjustmentCost()) > 0 ||
                        itemReq.getRefundAmount().compareTo(totalPaidIn) > 0 ||
                        adjustmentCost.compareTo(new BigDecimal(0)) <= 0 ) {
                    throw new BusinessException(SystemError.CUSTOM_ORDER_4016);
                }
            } else if (Objects.equals(RefundDetailTypeCode.COLLECTION.getCode(), itemReq.getRefundDetailTypeId())) {
                if (itemReq.getRefundAmount().compareTo(touristInfo.getCollectionFee()) > 0 ||
                        itemReq.getRefundAmount().compareTo(totalPaidIn) > 0) {
                    throw new BusinessException(SystemError.CUSTOM_ORDER_4016);
                }
            } else if (Objects.equals(RefundDetailTypeCode.OTHER.getCode(), itemReq.getRefundDetailTypeId())) {
                if (itemReq.getRefundAmount().compareTo(touristInfo.getTotalPaidIn()) > 0 ||
                        itemReq.getRefundAmount().compareTo(totalPaidIn) > 0) {
                    throw new BusinessException(SystemError.CUSTOM_ORDER_4016);
                }
            }

            //每次扣减
            totalPaidIn = totalPaidIn.subtract(itemReq.getRefundAmount());
            CustomizedOrderTouristRefundDetail detail = EntityUtil.copy(itemReq, CustomizedOrderTouristRefundDetail.class);
            detail.setRefundNumber(OrderUtil.getRefundNumber());
            detail.setRefundId(refundId);
            detail.setActualRefundAmount(BigDecimal.ZERO);
            detail.setTotalReceivables(touristInfo.getTotalReceivables());
            detail.setPaidInAmount(touristInfo.getTotalPaidIn());
            detail.setRefundDetailId(itemReq.getRefundDetailTypeId());
            detail.setRefundDetail(itemReq.getRefundDetailType());
            detail.setRefundStatus(2);
            detail.setGmtCreate(now);
            detail.setGmtModified(now);
            detail.setCreateId(req.getUserId());
            detail.setModifiedId(req.getUserId());
            detail.setIsDeleted(0);
            int insert2 = orderTouristRefundDetailMapper.insert(detail);
            if (insert2 <= 0){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        return Result.success(refund.getId());
    }


    /**
     * 发起审批流程
     * @param id
     * @param userId
     */
    private Long startApproval(Long id, Long orderId, Long userId,BigDecimal amount) {
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", id);
        try{
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.OUTBOUND_CUSTOMIZATION.getCode(),
                    SysApprovalType.REFUND_OUTCUSTOM.getCode(), orderId,
                    userId, amount, JSON.toJSONString(extendParams));
            if (!approvalResult.isSuccess()) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
            }
            return approvalResult.getData().getApprovalId();
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_422);
        }
    }


    /**
     * 退款明细
     *
     * @param req
     * @return
     */
    @Override
    public List<TouristRefundDetailListDTO> refundList(CustomOrderTouristIdReq req) {
        List<TouristRefundDetailListDTO> list = orderTouristRefundMapper.refundDetailList(req.getId());
        if (CollectionUtils.isNotEmpty(list)){
            list.forEach(dto -> {
                UserDTO userDTO = sysUserService.queryCacheUser(dto.getCreateId());
                if (userDTO != null){
                    dto.setSaleUserName(userDTO.getFullName());
                    dto.setSaleUserDept(userDTO.getDept());
                }
            });
            return list;
        }
        return null;
    }

    /**
     * 撤回
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result withdraw(CustomOrderRefundWithdrawReq req) {
        //查询记录
        CustomizedOrderTouristRefund refund = getById(req.getRefundId());
        if (refund == null){
            throw new BusinessException(SystemError.SYS_411);
        }
        //操作权限
        if (!Objects.equals(req.getUserId(),refund.getCreateId())){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4045);
        }
        //审批中状态才能撤回
        if (!Objects.equals(refund.getRefundStatus(), NumberConstant.TWO.getValue())){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4046);
        }
        //修改
        refund.setIsDeleted(1);
        refund.setModifiedId(req.getUserId());
        boolean bl = updateById(refund);
        //清空退款明细
        Integer clean = orderTouristRefundDetailMapper.cleanByRefund(refund.getId(),req.getUserId());
        if (!bl || clean <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(refund.getId());
    }

    /**
     * 添加计算（退款管理-退款）
     *
     * @param req
     * @return
     */
    @Override
    public Result<CustomOrderTouristRefundAddCalculationDTO> addCalculation(CustomOrderTouristRefundAddCalculationReq req) {
        QueryWrapper<CustomizedOrderAmountStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CustomizedOrderAmountStatistics::getOrderId, req.getOrderId());
        CustomizedOrderAmountStatistics statistics = orderAmountStatisticsMapper.selectOne(queryWrapper);
        if (statistics == null) {
            return Result.failed(SystemError.SYS_411);
        }
        //实收金额
        BigDecimal totalPaidIn = statistics.getTotalPaidIn();
        //查询优惠金额
        BigDecimal discountAmount = new BigDecimal(0);
        QueryWrapper<CustomizedOrderCollection> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(CustomizedOrderCollection::getOrderId, req.getOrderId());
        queryWrapper2.lambda().eq(CustomizedOrderCollection::getTouristId, req.getTouristId());
        queryWrapper2.lambda().and(object -> object.eq(CustomizedOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.BANK_PREFERENCE.getCode())
//                .or().eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.POINTS.getCode())
                .or().eq(CustomizedOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.OPERATE_PROMOTION.getCode()));
        queryWrapper2.lambda().eq(CustomizedOrderCollection::getIsDeleted, IsDeletedCode.NO.getCode());
        List<CustomizedOrderCollection> collectionList = orderCollectionMapper.selectList(queryWrapper2);
        for (CustomizedOrderCollection collection : collectionList) {
            discountAmount = discountAmount.add(collection.getPaidInAmount());
        }

        BigDecimal totalAmount = new BigDecimal(0);
        CustomOrderTouristRefundAddCalculationDTO dto = EntityUtil.copy(req, CustomOrderTouristRefundAddCalculationDTO.class);

        for (CustomOrderTouristRefundAddCalculationItemReq calculationItemReq : req.getItemList()) {
            if (calculationItemReq.getCurrencyTypeId() == null ||
                    Objects.equals(CurrencyIdCode.HKD.getCode(), calculationItemReq.getCurrencyTypeId())) {
                totalAmount = totalAmount.add(calculationItemReq.getCurrencyRefundAmount());
            } else {
                MainDataCurrencyUpdateStatusReq currencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
                currencyUpdateStatusReq.setId(calculationItemReq.getCurrencyTypeId());
                Result<MainDataCurrencyQueryDTO> currencyQueryDTOResult = mainDataCurrencyService.query(currencyUpdateStatusReq);
                if (!currencyQueryDTOResult.isSuccess() && currencyQueryDTOResult.getData() == null) {
                    return Result.failed(SystemError.SYS_411);
                }
                MainDataCurrencyQueryDTO currencyQueryDTO = currencyQueryDTOResult.getData();
                MathContext context = new MathContext(2, RoundingMode.HALF_DOWN);
                //其他貨幣金額=港幣金額÷對應的門市匯率
                BigDecimal refundAmount = calculationItemReq.getCurrencyRefundAmount().divide(currencyQueryDTO.getMarketExchangeRate(), context);
                totalAmount = totalAmount.add(refundAmount);
            }
        }
        dto.setTotalPaidIn(totalPaidIn);
        dto.setDiscountAmount(discountAmount);
        dto.setTotalAmount(totalAmount);
        return Result.success(dto);
    }

    /**
     * 操作退款
     *
     * @param req
     * @param currentUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result confirm(CustomOrderRefundWithdrawReq req, TokenUser currentUser) {
        CustomizedOrderTouristRefundDetail detail = orderTouristRefundDetailMapper.selectById(req.getRefundId());
        if (detail == null || Objects.equals(detail.getIsDeleted(),1)){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4049);
        }
        //审批通过才能操作退款
        if (!Objects.equals(detail.getRefundStatus(),3)){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4021);
        }
        detail.setRefundStatus(5);
        detail.setModifiedId(req.getUserId());
        Integer update = orderTouristRefundDetailMapper.updateById(detail);
        if (update <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        //更新统计
        CustomizedOrderTouristRefund refund = getById(detail.getRefundId());
        CustomizedOrderTouristInfo touristInfo = orderTouristInfoMapper.selectById(refund.getTouristId());
        touristInfo.setOtherAmount(touristInfo.getOtherAmount().subtract(detail.getActualRefundAmount()));
        touristInfo.setTotalPaidIn(touristInfo.getTotalPaidIn().subtract(detail.getActualRefundAmount()));
        touristInfo.setRefundAmount(touristInfo.getRefundAmount().add(detail.getActualRefundAmount()));
        touristInfo.setModifiedId(req.getUserId());
        int update1 = orderTouristInfoMapper.updateById(touristInfo);
        QueryWrapper<CustomizedOrderAmountStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id",refund.getOrderId());
        CustomizedOrderAmountStatistics amountStatistics = orderAmountStatisticsMapper.selectOne(queryWrapper);
        amountStatistics.setOtherAmount(amountStatistics.getOtherAmount().subtract(detail.getActualRefundAmount()));
        amountStatistics.setTotalPaidIn(amountStatistics.getTotalPaidIn().subtract(detail.getActualRefundAmount()));
        amountStatistics.setRefundAmount(amountStatistics.getRefundAmount().add(detail.getActualRefundAmount()));
        int update2 = orderAmountStatisticsMapper.updateById(amountStatistics);
        if (update1 <= 0 || update2 <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        //其他费用
        CustomizedOrderTouristOtherFee otherFee = new CustomizedOrderTouristOtherFee();
        otherFee.setId(SnowflakeIdWorker.nextId());
        otherFee.setFeeType(1);
        otherFee.setFeeName("退款");
        otherFee.setOrderId(touristInfo.getOrderId());
        otherFee.setTouristId(touristInfo.getId());
        otherFee.setRelationId(detail.getId());
        otherFee.setAmount(detail.getActualRefundAmount());
        otherFee.setGmtCreate(LocalDateTime.now());
        otherFee.setCreateId(req.getUserId());
        otherFee.setIsDeleted(0);
        int insert = orderTouristOtherFeeMapper.insert(otherFee);
        if (insert <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        //对接财务操作退款
        BillOperateRefundReq req1 = new BillOperateRefundReq();
        req1.setBillNumber(detail.getRefundNumber());
        req1.setBusinessType(SystemBusinessType.OUTBOUND_CUSTOMIZATION.getCode());
        req1.setUserId(currentUser.getId());
        Result result = financeBillService.operateRefund(req1);
        if (result == null || !result.isSuccess()){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(detail.getId());
    }

    /**
     * 退款(内部接口)
     *
     * @param refundNumber
     * @param currentUser
     * @return
     */
    @Override
    public Result confirmRefund(String refundNumber, TokenUser currentUser) {
        QueryWrapper<CustomizedOrderTouristRefundDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("refund_number",refundNumber);
        queryWrapper.eq("is_deleted",0);
        CustomizedOrderTouristRefundDetail detail = orderTouristRefundDetailMapper.selectOne(queryWrapper);
        if (detail == null){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4049);
        }
        //审批通过才能操作退款
        if (!Objects.equals(detail.getRefundStatus(),3)){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4021);
        }
        detail.setRefundStatus(5);
        detail.setModifiedId(currentUser.getId());
        Integer update = orderTouristRefundDetailMapper.updateById(detail);
        if (update <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(detail.getId());
    }

    /**
     * 财务中心-销售订单退款-退款详情-退款明细列表（内部接口）
     *
     * @param refundNumber 退款单号
     * @return
     */
    @Override
    public Result<List<OrderRefundDTO>> refundDetailList(String refundNumber) {
        QueryWrapper<CustomizedOrderTouristRefundDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("refund_number",refundNumber);
        queryWrapper.eq("is_deleted",0);
        CustomizedOrderTouristRefundDetail detail = orderTouristRefundDetailMapper.selectOne(queryWrapper);
        if (detail == null){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4049);
        }
        //退款信息列表
        List<OrderRefundDTO> list = orderTouristRefundDetailMapper.queryListByRefund(detail.getRefundId());
        if (CollectionUtils.isNotEmpty(list)){
            list.forEach(dto -> {
                //业务类型
                dto.setBusinessType(SystemBusinessType.OUTBOUND_CUSTOMIZATION.getCode());
            });
        }
        return Result.success(list);
    }

    /**
     * 审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result approval(RefundApprovalReq req) {
        QueryWrapper<CustomizedOrderTouristRefund> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_id",req.getId());
        queryWrapper.eq("is_deleted",0);
        CustomizedOrderTouristRefund refund = orderTouristRefundMapper.selectOne(queryWrapper);
        if (refund == null){
            throw new BusinessException(SystemError.SYS_411);
        }
        refund.setRefundStatus(req.getType());
        refund.setModifiedId(req.getUserId());
        Integer update = orderTouristRefundMapper.updateById(refund);
        //更新状态
        if (update <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        if (Objects.equals(req.getType(),4)){
            orderTouristRefundDetailMapper.updateStatusByRefund(refund.getId(),req.getType(),req.getUserId());
        }else if (Objects.equals(req.getType(),3)){
            //审批通过
            if (CollectionUtils.isNotEmpty(req.getRefundAmountList())){
                List<BillAddRefundReq> reqList = new ArrayList<>();
                //退款总金额
                BigDecimal totalRefundAmount = BigDecimal.ZERO;
                for (RefundAmountReq req2 : req.getRefundAmountList()){
                    CustomizedOrderTouristRefundDetail detail = orderTouristRefundDetailMapper.selectById(req2.getId());
                    if (detail != null && Objects.equals(detail.getIsDeleted(),0)){
                        totalRefundAmount = totalRefundAmount.add(req2.getRefundAmount());
                        detail.setRefundStatus(req.getType());
                        detail.setActualRefundAmount(req2.getRefundAmount());
                        detail.setModifiedId(req.getUserId());
                        int update1 = orderTouristRefundDetailMapper.updateById(detail);
                        if (update1 <= 0){
                            throw new BusinessException(SystemError.SYS_437);
                        }
                        //审批通过，对接财务中心新增退款认款
                        CustomizedOrder order = orderMapper.selectById(refund.getOrderId());
                        CustomizedTripScheduleDTO tripSchedule = tripScheduleService.queryByScheduleId(refund.getScheduleId());
                        UserDTO userDTO = sysUserService.queryCacheUser(detail.getCreateId());
                        //新增退款认款请求参数
                        BillAddRefundReq req1 = packBillAddRefundReq(refund,detail,order,tripSchedule,userDTO,req.getUserId());
                        reqList.add(req1);
                    }
                }
                //更新退款总表金额
                if (totalRefundAmount.compareTo(refund.getRefundAmount()) != 0){
                    refund.setRefundAmount(totalRefundAmount);
                    Integer update2 = orderTouristRefundMapper.updateById(refund);
                    if (update2 <= 0){
                        throw new BusinessException(SystemError.SYS_437);
                    }
                }

                //新增财务退款认款记录
                Result result = financeBillService.addRefund(reqList);
                if (refund == null || !result.isSuccess()){
                    throw new BusinessException(SystemError.SYS_437);
                }
            }
        }
        Boolean bl = checkApproval(refund.getApprovalId(), req.getType(), req.getUserId(), req.getRemark());
        if (!bl){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(refund.getId());
    }

    /**
     * 不成团-退指定团期所有订单的保险（内部接口）
     *
     * @param schedule
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result refundInsuranceBySchedule(Long schedule, Long userId) {
        //获取团期参保记录
        QueryWrapper<CustomizedOrderInsurance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("schedule_id",schedule);
        queryWrapper.eq("is_deleted",0);
        List<CustomizedOrderInsurance> insuranceList = orderInsuranceMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(insuranceList)){
            //退保总金额
            BigDecimal totalRefundAmount = BigDecimal.ZERO;
            //退保请求参数
            List<CancelReq> reqList = new ArrayList<>();
            for (CustomizedOrderInsurance insurance : insuranceList){
                totalRefundAmount = totalRefundAmount.add(insurance.getTotalAmount());
                QueryWrapper<CustomizedOrderInsuranceJoin> joinWrapper = new QueryWrapper<>();
                joinWrapper.eq("insurance_id",insurance.getId());
                joinWrapper.eq("is_deleted",0);
                CustomizedOrderInsuranceJoin join = orderInsuranceJoinMapper.selectOne(joinWrapper);
                if (join != null){
                    CancelReq cancelReq = new CancelReq();
                    cancelReq.setPolicyNo(join.getPolicyNo());
                    cancelReq.setOperatorCode(PacificUtil.OPERATORCODE);
                    reqList.add(cancelReq);
                }
            }
            if (CollectionUtils.isNotEmpty(reqList)){
                //退保
                List<CancelDTO> cancel = null;
                try {
                    cancel = insuranceService.policyCancel(reqList);
                }catch (Exception e){
                    throw new BusinessException(SystemError.CUSTOM_ORDER_4026);
                }
                //退保成功
                if (CollectionUtils.isNotEmpty(cancel)){
                    //查询订单保险总金额列表
                    List<OrderInsuranceAmountListDTO> orderInsuranceAmountList =  orderInsuranceMapper.sumAmountByOrder(schedule);
                    if (CollectionUtils.isNotEmpty(orderInsuranceAmountList)){
                        for (OrderInsuranceAmountListDTO amountDTO : orderInsuranceAmountList){
                            //更新订单金额统计
                            QueryWrapper<CustomizedOrderAmountStatistics> statisticsWrapper = new QueryWrapper<>();
                            statisticsWrapper.eq("order_id",amountDTO.getOrderId());
                            CustomizedOrderAmountStatistics statistics = orderAmountStatisticsMapper.selectOne(statisticsWrapper);
                            if (statistics != null){
                                statistics.setTotalReceivables(statistics.getTotalReceivables().subtract(amountDTO.getTotalAmount()));
                                statistics.setTotalPaidIn(statistics.getTotalPaidIn().subtract(amountDTO.getTotalAmount()));
                                statistics.setReceiptedAmount(statistics.getReceiptedAmount().subtract(amountDTO.getTotalAmount()));
                                int update = orderAmountStatisticsMapper.updateById(statistics);
                                if (update <= 0){
                                    throw new BusinessException(SystemError.SYS_437);
                                }
                            }
                        }
                    }
                    //删除团期保险记录
                    Integer batchDelInsurance = orderInsuranceMapper.delBySchedule(schedule,userId);
                    //删除团期参保记录
                    Integer batchDelJoin = orderInsuranceJoinMapper.delBySchedule(schedule,userId);
                    //查询旅客参保记录
                    QueryWrapper<CustomizedOrderInsurancePriceTourist> queryWrapper1 = new QueryWrapper<>();
                    queryWrapper1.eq("schedule_id",schedule);
                    List<CustomizedOrderInsurancePriceTourist> priceTouristList = orderInsurancePriceTouristMapper.selectList(queryWrapper1);
                    if (CollectionUtils.isNotEmpty(priceTouristList)){
                        for (CustomizedOrderInsurancePriceTourist priceTourist : priceTouristList){
                            //更新旅客金额统计
                            CustomizedOrderTouristInfo touristInfo = orderTouristInfoMapper.selectById(priceTourist.getTouristId());
                            if (touristInfo != null){
                                touristInfo.setTotalReceivables(touristInfo.getTotalReceivables().subtract(priceTourist.getAmount()));
                                touristInfo.setTotalPaidIn(touristInfo.getTotalPaidIn().subtract(priceTourist.getAmount()));
                                touristInfo.setReceiptedAmount(touristInfo.getReceiptedAmount().subtract(priceTourist.getAmount()));
                                int update = orderTouristInfoMapper.updateById(touristInfo);
                                if (update <= 0){
                                    throw new BusinessException(SystemError.SYS_437);
                                }
                            }
                        }
                        //删除旅客参保记录
                        Integer batchDelTourist = orderInsurancePriceTouristMapper.delBySchedule(schedule);
                        if (batchDelTourist < priceTouristList.size()){
                            throw new BusinessException(SystemError.SYS_437);
                        }
                    }
                    //团期保单收据作废
                    Integer batchDelReceipt = orderReceiptInsuranceMapper.delBySchedule(schedule,userId);
                    if (batchDelInsurance < insuranceList.size() || batchDelJoin <= 0 || batchDelReceipt <= 0){
                        throw new BusinessException(SystemError.SYS_437);
                    }
                }
            }
        }
        return Result.success();
    }

    /**
     * 审批中心-退款信息列表
     *
     * @param req
     * @return
     */
    @Override
    public Result<List<ApprovalRefundListDTO>> approvalRefundList(ApprovalIdReq req) {
        QueryWrapper<CustomizedOrderTouristRefund> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_id",req.getApprovalId());
        queryWrapper.eq("is_deleted",0);
        CustomizedOrderTouristRefund refund = orderTouristRefundMapper.selectOne(queryWrapper);
        if (refund == null){
            throw new BusinessException(SystemError.SYS_411);
        }
        QueryWrapper<CustomizedOrderTouristRefundDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.eq("refund_id",refund.getId());
        detailQueryWrapper.eq("is_deleted",0);
        List<CustomizedOrderTouristRefundDetail> detailList = orderTouristRefundDetailMapper.selectList(detailQueryWrapper);
        List<ApprovalRefundListDTO> dtoList = new ArrayList<>();
        for (CustomizedOrderTouristRefundDetail detail : detailList){
            ApprovalRefundListDTO dto = EntityUtil.copy(detail,ApprovalRefundListDTO.class);
            dto.setRefundWay(detail.getRefundType());
            if (detail.getCreateId() != null){
                UserDTO userDTO = sysUserService.queryCacheUser(detail.getCreateId());
                if (userDTO != null){
                    dto.setApprovalUser(userDTO.getFullName());
                    dto.setCreateUserDept(userDTO.getDept());
                }
                dtoList.add(dto);
            }
        }
        return Result.success(dtoList);
    }

    /**
     * 新增退款认款请求参数
     * @param refund
     * @param detail
     * @param order
     * @param tripSchedule
     * @param userDTO
     * @param userId
     * @return
     */
    private BillAddRefundReq packBillAddRefundReq(CustomizedOrderTouristRefund refund, CustomizedOrderTouristRefundDetail detail, CustomizedOrder order, CustomizedTripScheduleDTO tripSchedule, UserDTO userDTO, Long userId) {
        BillAddRefundReq req1 = new BillAddRefundReq();
        req1.setBillNumber(detail.getRefundNumber());
        req1.setBusinessType(SystemBusinessType.OUTBOUND_CUSTOMIZATION.getCode());
        req1.setCollectionAmount(detail.getActualRefundAmount());
        req1.setCurrencyId(detail.getCurrencyId());
        req1.setCurrencyName(detail.getCurrency());
        req1.setExchangeRate(detail.getExchangeRate());
        req1.setSaleOrderNumber(order.getOrderNumber());
        req1.setSaleOrderId(order.getId());
        req1.setProductNumber(tripSchedule.getTripNumber());
        req1.setProductName(tripSchedule.getName());
        List<String> resourceInfo = new ArrayList<>();
        resourceInfo.add(tripSchedule.getName());
        req1.setResourceInfo(resourceInfo);
        req1.setSaleUserId(refund.getCreateId());
        req1.setSaleDeptId(userDTO.getDeptId());
        req1.setSaleUserName(userDTO.getFullName());
        req1.setRefundTypeId(detail.getRefundDetailId());
        req1.setRefundType(detail.getRefundDetail());
        req1.setTypeId(detail.getRefundTypeId());
        req1.setType(detail.getRefundType());
        AccountJson refundAccountJson = new AccountJson();
        refundAccountJson.setCardNumber(detail.getRefundAccount());
        req1.setRefundAccountJson(refundAccountJson);
        req1.setRefundTime(refund.getGmtCreate());
        req1.setRefundRemark(detail.getRemark());
        req1.setUserId(userId);
        req1.setScheduleId(tripSchedule.getId());
        return req1;
    }

    /**
     * 业务审批
     * @param approvalId    审批id(必填)
     * @param userId        审批人id(必填)
     * @param status        状态-ApprovalStatus枚举code 0 撤回 3 审批不通过 4 审批通过(必填)
     * @param comments      通过或拒绝评论说明(非必填)
     * @return
     */
    private Boolean checkApproval(Long approvalId, Integer status, Long userId,String comments){
        Result<ApprovalCheckDTO> result = sysApprovalService.check(approvalId, userId, status, comments);
        if (result != null && result.isSuccess()){
            return result.getData().getIsFinish();
        }
        return false;
    }

}
